<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 1. 允许用户自定义一个元素 随便起名字
    2. shadow DOM 样式隔离是web components 的核心
    3. HTML 模板 插槽 生命周期 属性 都是组件的特点 -->
    <my-button type="primary"></my-button>
    <!-- template 是html的内置元素,但是它不会展示在页面上 -->
    <template id="my-button-template">

        <button>
            <slot>按钮</slot>
        </button>
    </template>

    <script>
        //MACRO-APP 核心是把应用的模版和样式进行隔离,然后通过shadow DOM来实现
        class MyButton extends HTMLElement {
            connectedCallback() {  // 类似vue mounted

                // my-button 元素挂载完成后,我们需要获取传入的属性,并且使用对应的模版来渲染
                console.log(this, '11111')

                this.shadow = this.attachShadow({ mode: 'closed' }); // 创建一个shadow DOM
                let btn = document.getElementById('my-button-template') // 获取模版===>在mcro-app中就是获取对应的应用模版
                let btnType = this.getAttribute('type') || 'default'; // 获取传入的属性
                let types = {
                    primary: {
                        backgroundColor: 'blue'
                    },
                    default: {
                        backgroundColor: 'gray'
                    },
                    danger: {
                        backgroundColor: 'red'
                    }
                }
                this.types = types; // 将类型存储在组件实例上
                let s = document.createElement('style'); // 创建一个style元素
                s.innerHTML = `
                    button {
                        background-color: ${types[btnType].backgroundColor};
                        color: #fff;
                        border: none;
                        padding: 10px 20px;
                        border-radius: 5px;
                        cursor: pointer;
                    }
                    button:hover {
                        opacity: 0.8;
                    }
                `;
                let tpl = btn.content.cloneNode(true); // 克隆模版内容
                this.shadow.appendChild(s); // 将样式添加到shadow DOM中---样式隔离
                this.shadow.appendChild(tpl); // 将克隆的内容添加到shadow DOM中---dom隔离
                //派发事件
                this.dispatchEvent(new CustomEvent('mounted'));

            }
            // 监听属性变化
            static get observedAttributes() {
                return ['type'];
            }
            // 当属性变化时会触发这个方法
            attributeChangedCallback(name, oldValue, newValue) { // 类似vue watch
                console.log(name, oldValue, newValue);
                if (this.shadow) {
                    const btn = this.shadow.querySelector('button');
                    btn.style.backgroundColor = this.types[newValue]?.backgroundColor || 'gray'; // 更新样式
                    this.dispatchEvent(new CustomEvent('update'));
                }
            }
            // 组件销毁时触发
            disconnectedCallback() {
                console.log('组件被销毁了');
            }
            // 组件更新时触发 ---//移除-移动组件时触发
            adoptedCallback() {
                console.log('移除组件时触发');
            }
        }
        const customBtn = document.querySelector('my-button');

        // 挂载--当然可以监听
        customBtn.addEventListener('mounted', (e) => {
            console.log('挂在了'); // 按钮被点击了
        });
        customBtn.addEventListener('update', (e) => {
            console.log('更新了'); // 按钮被点击了
        });
        window.customElements.define('my-button', MyButton);



        setTimeout(() => {
            customBtn.setAttribute('type', 'danger'); // 修改属性
        }, 2000);
    </script>
</body>

</html>